/**
 * 通用工具函数
 */

/**
 * 格式化日期时间
 * @param {Date|string} date 日期
 * @param {string} format 格式化模板
 * @returns {string} 格式化后的日期字符串
 */
function formatDateTime(date, format = 'YYYY-MM-DD HH:mm:ss') {
  if (!date) return ''

  const d = new Date(date)
  const year = d.getFullYear()
  const month = String(d.getMonth() + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2, '0')
  const hour = String(d.getHours()).padStart(2, '0')
  const minute = String(d.getMinutes()).padStart(2, '0')
  const second = String(d.getSeconds()).padStart(2, '0')

  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('HH', hour)
    .replace('mm', minute)
    .replace('ss', second)
}

/**
 * 格式化日期
 * @param {Date|string} date 日期
 * @returns {string} 格式化后的日期字符串
 */
function formatDate(date) {
  return formatDateTime(date, 'YYYY-MM-DD')
}

/**
 * 格式化时间
 * @param {Date|string} date 日期
 * @returns {string} 格式化后的时间字符串
 */
function formatTime(date) {
  return formatDateTime(date, 'HH:mm:ss')
}

/**
 * 格式化金额
 * @param {number} amount 金额
 * @param {number} decimals 小数位数
 * @param {string} decimalPoint 小数点
 * @param {string} thousandsSeparator 千位分隔符
 * @returns {string} 格式化后的金额字符串
 */
function formatMoney(amount, decimals = 2, decimalPoint = '.', thousandsSeparator = ',') {
  if (isNaN(amount)) return '0.00'

  const num = Number(amount)
  const fixedNum = num.toFixed(decimals)
  const parts = fixedNum.split('.')

  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator)

  return parts.join(decimalPoint)
}

/**
 * 格式化价格显示
 * @param {number} price 价格
 * @returns {string} 格式化后的价格字符串
 */
function formatPrice(price) {
  return `¥${formatMoney(price)}`
}

/**
 * 获取相对时间
 * @param {Date|string} date 日期
 * @returns {string} 相对时间字符串
 */
function getRelativeTime(date) {
  if (!date) return ''

  const now = new Date()
  const target = new Date(date)
  const diff = now - target

  const seconds = Math.floor(diff / 1000)
  const minutes = Math.floor(seconds / 60)
  const hours = Math.floor(minutes / 60)
  const days = Math.floor(hours / 24)

  if (days > 0) return `${days}天前`
  if (hours > 0) return `${hours}小时前`
  if (minutes > 0) return `${minutes}分钟前`
  return '刚刚'
}

/**
 * 防抖函数
 * @param {Function} func 要防抖的函数
 * @param {number} wait 等待时间
 * @returns {Function} 防抖后的函数
 */
function debounce(func, wait) {
  let timeout
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout)
      func(...args)
    }
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
  }
}

/**
 * 节流函数
 * @param {Function} func 要节流的函数
 * @param {number} limit 时间限制
 * @returns {Function} 节流后的函数
 */
function throttle(func, limit) {
  let inThrottle
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args)
      inThrottle = true
      setTimeout(() => inThrottle = false, limit)
    }
  }
}

/**
 * 深拷贝
 * @param {*} obj 要拷贝的对象
 * @returns {*} 拷贝后的对象
 */
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj)
  if (obj instanceof Array) return obj.map(item => deepClone(item))
  if (typeof obj === 'object') {
    const clonedObj = {}
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        clonedObj[key] = deepClone(obj[key])
      }
    }
    return clonedObj
  }
}

/**
 * 获取任务状态文本
 * @param {number} status 状态码
 * @returns {string} 状态文本
 */
function getTaskStatusText(status) {
  const statusMap = {
    1: '已领取',
    2: '待审核',
    3: '已完成',
    4: '已驳回',
    5: '已回收'
  }
  return statusMap[status] || '未知状态'
}

/**
 * 获取任务状态样式类
 * @param {number} status 状态码
 * @returns {string} 样式类名
 */
function getTaskStatusClass(status) {
  const classMap = {
    1: 'status-pending',
    2: 'status-pending',
    3: 'status-completed',
    4: 'status-rejected',
    5: 'status-approved'
  }
  return classMap[status] || ''
}

/**
 * 获取用户等级文本
 * @param {number} level 等级
 * @returns {string} 等级文本
 */
function getUserLevelText(level) {
  const levelMap = {
    1: '普通用户',
    2: '高级用户',
    3: 'VIP用户'
  }
  return levelMap[level] || '未知等级'
}

/**
 * 获取用户状态文本
 * @param {number} status 状态码
 * @returns {string} 状态文本
 */
function getUserStatusText(status) {
  const statusMap = {
    0: '待审核',
    1: '正常',
    2: '冻结',
    3: '黑名单'
  }
  return statusMap[status] || '未知状态'
}

/**
 * 获取难度等级文本
 * @param {number} level 难度等级
 * @returns {string} 难度文本
 */
function getDifficultyText(level) {
  const levelMap = {
    1: '简单',
    2: '中等',
    3: '困难'
  }
  return levelMap[level] || '未知难度'
}

/**
 * 获取难度等级星星数
 * @param {number} level 难度等级
 * @returns {number} 星星数
 */
function getDifficultyStars(level) {
  return level || 1
}

/**
 * 验证手机号
 * @param {string} phone 手机号
 * @returns {boolean} 是否有效
 */
function validatePhone(phone) {
  const phoneRegex = /^1[3-9]\d{9}$/
  return phoneRegex.test(phone)
}

/**
 * 验证身份证号
 * @param {string} idCard 身份证号
 * @returns {boolean} 是否有效
 */
function validateIdCard(idCard) {
  const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  return idCardRegex.test(idCard)
}

/**
 * 显示成功提示
 * @param {string} title 提示内容
 * @param {number} duration 持续时间
 */
function showSuccess(title, duration = 2000) {
  wx.showToast({
    title,
    icon: 'success',
    duration
  })
}

/**
 * 显示错误提示
 * @param {string} title 提示内容
 * @param {number} duration 持续时间
 */
function showError(title, duration = 2000) {
  wx.showToast({
    title,
    icon: 'none',
    duration
  })
}

/**
 * 显示加载提示
 * @param {string} title 提示内容
 */
function showLoading(title = '加载中...') {
  wx.showLoading({
    title,
    mask: true
  })
}

/**
 * 隐藏加载提示
 */
function hideLoading() {
  wx.hideLoading()
}

/**
 * 显示确认对话框
 * @param {string} content 内容
 * @param {string} title 标题
 * @returns {Promise<boolean>} 是否确认
 */
function showConfirm(content, title = '提示') {
  return new Promise((resolve) => {
    wx.showModal({
      title,
      content,
      success: (res) => {
        resolve(res.confirm)
      }
    })
  })
}

/**
 * 获取系统信息
 * @returns {Promise<Object>} 系统信息
 */
function getSystemInfo() {
  return new Promise((resolve) => {
    wx.getSystemInfo({
      success: resolve
    })
  })
}

/**
 * 选择图片
 * @param {number} count 最多选择的图片数量
 * @param {Array} sourceType 图片来源
 * @returns {Promise<Array>} 选择的图片路径数组
 */
function chooseImage(count = 1, sourceType = ['album', 'camera']) {
  return new Promise((resolve, reject) => {
    wx.chooseImage({
      count,
      sourceType,
      success: resolve,
      fail: reject
    })
  })
}

/**
 * 上传图片
 * @param {string} filePath 图片路径
 * @param {Object} data 额外数据
 * @returns {Promise<Object>} 上传结果
 */
function uploadImage(filePath, data = {}) {
  return new Promise((resolve, reject) => {
    wx.uploadFile({
      url: `${apiService.baseURL}/upload/image`,
      filePath,
      name: 'file',
      formData: data,
      header: {
        'Authorization': `Bearer ${apiService.getToken()}`
      },
      success: (res) => {
        try {
          const data = JSON.parse(res.data)
          resolve(data)
        } catch (e) {
          reject(e)
        }
      },
      fail: reject
    })
  })
}

module.exports = {
  formatDateTime,
  formatDate,
  formatTime,
  formatMoney,
  formatPrice,
  getRelativeTime,
  debounce,
  throttle,
  deepClone,
  getTaskStatusText,
  getTaskStatusClass,
  getUserLevelText,
  getUserStatusText,
  getDifficultyText,
  getDifficultyStars,
  validatePhone,
  validateIdCard,
  showSuccess,
  showError,
  showLoading,
  hideLoading,
  showConfirm,
  getSystemInfo,
  chooseImage,
  uploadImage
}

/**
 * 格式化文件大小
 * @param {number} bytes 字节数
 * @returns {string} 格式化后的文件大小
 */
function formatFileSize(bytes) {
  if (!bytes || bytes === 0) return '0 B'

  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  const k = 1024
  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + units[i]
}

/**
 * 格式化数字
 * @param {number} num 数字
 * @param {number} decimals 小数位数
 * @returns {string} 格式化后的数字字符串
 */
function formatNumber(num, decimals = 0) {
  if (!num && num !== 0) return '0'

  const n = parseFloat(num)
  if (isNaN(n)) return '0'

  return n.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

/**
 * 检查是否为空
 * @param {*} value 要检查的值
 * @returns {boolean} 是否为空
 */
function isEmpty(value) {
  return value === null || value === undefined || value === '' ||
         (Array.isArray(value) && value.length === 0) ||
         (typeof value === 'object' && Object.keys(value).length === 0)
}

/**
 * 深度比较两个值是否相等
 * @param {*} a 值A
 * @param {*} b 值B
 * @returns {boolean} 是否相等
 */
function isEqual(a, b) {
  if (a === b) return true

  if (a && b && typeof a === 'object' && typeof b === 'object') {
    if (Array.isArray(a) !== Array.isArray(b)) return false

    const keysA = Object.keys(a)
    const keysB = Object.keys(b)

    if (keysA.length !== keysB.length) return false

    for (let key of keysA) {
      if (!keysB.includes(key) || !isEqual(a[key], b[key])) {
        return false
      }
    }

    return true
  }

  return false
}

/**
 * 生成随机字符串
 * @param {number} length 字符串长度
 * @param {string} charset 字符集
 * @returns {string} 随机字符串
 */
function randomString(length = 8, charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
  let result = ''
  for (let i = 0; i < length; i++) {
    result += charset.charAt(Math.floor(Math.random() * charset.length))
  }
  return result
}

/**
 * 生成UUID
 * @returns {string} UUID字符串
 */
function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0
    const v = c === 'x' ? r : (r & 0x3 | 0x8)
    return v.toString(16)
  })
}

module.exports = {
  formatDateTime,
  formatDate,
  formatTime,
  formatPrice,
  formatMoney,
  formatFileSize,
  formatNumber,
  getRelativeTime,
  debounce,
  throttle,
  deepClone,
  isEmpty,
  isEqual,
  randomString,
  generateUUID,
  getTaskStatusText,
  getTaskStatusClass,
  getUserLevelText,
  getUserStatusText,
  getDifficultyText,
  getDifficultyStars,
  validatePhone,
  validateIdCard,
  showSuccess,
  showError,
  showLoading,
  hideLoading,
  showConfirm,
  getSystemInfo,
  chooseImage,
  uploadImage
}